home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 142
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan).7z
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan) (Track 1).bin
/
ikap
/
etc2
/
src.lzh
/
tr68k.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-04
|
30KB
|
1,250 lines
/* 楽器の弾けない私から、楽器の弾けない貴方へ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/dos.h>
#include <sys/iocs.h>
#include <sys/xglob.h>
#define GLOBAL_DEFINE /* グローバル変数を確保する */
#include "tr68k.h"
#include "sound.h"
#include "pcm8call.h"
#define SC_BGX 12 /* 楽譜?部の BGTEXT 上の座標 */
#define SC_BGY 16
#define ACTIVE_BGX 29
#define TEMPO_BGX 3 /* テンポ表示(数字)の BGTEXT 上の座標 */
#define TEMPO_BGY 12
#define COPY_BGX 12 /* [COPY] の BGTEXT 上の座標 */
#define COPY_BGY 26
#define PASTE_BGX 14 /* [PASTE] の BGTEXT 上の座標 */
#define PASTE_BGY 26
#define SAVE_BGX 26 /* [SAVE] の BGTEXT 上の座標 */
#define SAVE_BGY 26
#define CHASE_BGX 4 /* [CHASE] の BGTEXT 上の座標 */
#define CHASE_BGY 27
#define LOOP_BGX 2 /* [LOOP] の BGTEXT 上の座標 */
#define LOOP_BGY 27
#define BARNO_BGX 19 /* 小節表示(数字)の BGTEXT 上の座標 */
#define BARNO_BGY 12
#define MAXBARNO_BGX 24 /* 最大小節表示(数字)の BGTEXT 上の座標 */
#define MAXBARNO_BGY BARNO_BGY
/* BG テキストの番号 */
#define BG_NOTE 0x10 /* 音符 */
/* パレットの番号<<16 */
#define PAL_TYPE0 0x0200 /* 音色タイプ0のパレット */
#define PAL_FLASH 0x0600 /* 光る音符のパレット */
#define PAL_NUMBER 0x0200 /* 数字のパレット */
/* BG テキスト+パレット<<16の番号 */
#define BGPAL_UPDOWN 0x022b /* 矢印 */
#define BGPAL_TRACK_ACTIVE 0x023d
#define BGPAL_TRACK_INACTIVE 0x022d
#define BGPAL_BUTTON32 0x022e
#define BGPAL_BUTTON32_UP 0x024e
#define BGPAL_LAMP_ACTIVE 0x065d
#define BGPAL_LAMP_INACTIVE 0x054d
#define REPEAT_1ST 30 /* 最初にキーリピートするまでの時間 */
#define REPEAT_2ND 5 /* 2回目以降キーリピートするまでの時間 */
static char track_active[TRACK_MAX]; /* トラックが有効か(画面左端のランプ) */
static char copy_volume[TRACK_MAX][NOTE_DISP]; /* コピーバッファ */
static char copy_type[TRACK_MAX][NOTE_DISP];
static int tempo; /* VDISP60SEC/tempo 回が note_tempo */
static int chase = 0; /* 演奏中の小節を追いかけるか */
static int loop = 0; /* 現在演奏中の小節をループするか */
static int pause = 0; /* ポーズ中 */
static int bar_disp = 0; /* 現在表示中の小節 */
static int bar_play = 0; /* 現在演奏中の小節 */
static int type_current = 0;
#define RGB(r,g,b) ((g)<<11|(r)<<6|(b)<<1)
/* イベントフラグ */
enum {
EVENT_MSLRUP = 0, EVENT_MSLDOWN, EVENT_MSRDOWN, EVENT_MSLRDOWN, EVENT_KEYDOWN,
};
/* イベント構造体 */
typedef struct {
char type; /* イベントの種類 */
char old_type; /* イベントの種類 */
unsigned short mouse_x; /* マウスカーソルの座標 */
unsigned short mouse_y;
unsigned short mouse_button;
unsigned short mouse_pat;
unsigned short old_mouse_x; /* 前のマウスカーソルの座標 */
unsigned short old_mouse_y;
unsigned short old_mouse_pat;
int keycode; /* キーコード */
int work1, work2;
char shift_key; /* =!0:シフトキーが押されている */
} EVENTREC;
/* キーコード */
enum {
KEYDOWN_NON = 0, KEYDOWN_LEFT, KEYDOWN_RIGHT, KEYDOWN_ESC, KEYDOWN_BREAK,
KEYDOWN_UP, KEYDOWN_DOWN, KEYDOWN_ROLLUP, KEYDOWN_ROLLDOWN, KEYDOWN_UNDO, KEYDOWN_DEL,
KEYDOWN_XF1, KEYDOWN_XF2,
KEYDOWN_Z, KEYDOWN_X, KEYDOWN_C, KEYDOWN_V,
KEYDOWN_SPACE,
};
static char *sp_data = NULL;
static char *pal_data = NULL;
static int screen_init = 0;
extern int apic_load (char *, int, int);
void usage (void)
{
puts ("Moland TR-68K ver0.90909\n"
" programmed by Mitsuky <FreeSoftware>\n"
"TR シリーズ風リズムマシンです\n"
"使用法 : TR68K [.ZMSファイル名]\n"
".ZMSファイル名無指定時には TR68K.ZMS を読み込みます\n"
);
}
/* アップダウンボタンを1セット表示 */
void DispUpdown (int x, int y)
{
_iocs_bgtextst (0, x, y, BGPAL_UPDOWN);
_iocs_bgtextst (0, x + 1, y, BGPAL_UPDOWN + 1);
_iocs_bgtextst (0, x, y + 1, BGPAL_UPDOWN + 0x10);
_iocs_bgtextst (0, x + 1, y + 1, BGPAL_UPDOWN + 0x11);
}
/* 数字を1個表示 */
void DispOneNumber (int x, int y, int no)
{
_iocs_bgtextst (0, x, y, PAL_NUMBER + 0x20 + no);
_iocs_bgtextst (0, x, y + 1, PAL_NUMBER + 0x30 + no);
}
/* 2桁の数字を表示 */
void DispTwoNumber (int x, int y, int no)
{
int n1, n2;
int flag = 0;
n1 = no / 10;
n2 = no - n1 * 10;
if (n1 > 0) {
DispOneNumber (x, y, n1);
flag = !0;
} else {
DispOneNumber (x, y, 10); /* 10 は LED 消灯表示 */
}
DispOneNumber (x + 1, y, n2);
}
/* 3桁の数字を表示 */
void DispThreeNumber (int x, int y, int no)
{
int n1, n2, n3;
int flag = 0;
n1 = no / 100;
n2 = (no - n1 * 100) / 10;
n3 = (no - n1 * 100 - n2 * 10);
if (n1 > 0) {
DispOneNumber (x, y, n1);
flag = !0;
} else {
DispOneNumber (x, y, 10); /* 10 は LED 消灯表示 */
}
if ((n2 > 0) || (flag)) {
DispOneNumber (x + 1, y, n2);
} else {
DispOneNumber (x + 1, y, 10); /* 10 は LED 消灯表示 */
}
DispOneNumber (x + 2, y, n3);
}
/* 音符を光らせる */
void FlashNote (int note_no)
{
static int old_bar_disp = 0;
static int old_note_no = 0;
int j;
if (old_bar_disp == bar_disp) {
for (j = 0; j < TRACK_MAX; j++)
if (track_active[j])
_iocs_bgtextst (0, SC_BGX + old_note_no, SC_BGY + j,
PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + old_note_no] << 8) + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + old_note_no]);
else
_iocs_bgtextst (0, SC_BGX + old_note_no, SC_BGY + j,
PAL_TYPE0 + BG_NOTE);
}
old_bar_disp = bar_disp;
if (bar_play == bar_disp) {
for (j = 0; j < TRACK_MAX; j++)
if (track_active[j])
_iocs_bgtextst (0, SC_BGX + note_no, SC_BGY + j,
PAL_FLASH + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + note_no]);
else
_iocs_bgtextst (0, SC_BGX + note_no, SC_BGY + j,
PAL_FLASH + BG_NOTE);
}
old_note_no = note_no;
}
/* 32x32ドットのボタンを表示 */
void DispButton32 (int x, int y, int s)
{
switch (s) {
case 0:
_iocs_bgtextst (0, x, y, BGPAL_BUTTON32);
_iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32 + 1);
_iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32 + 0x10);
_iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32 + 0x11);
break;
case 1:
_iocs_bgtextst (0, x, y, BGPAL_BUTTON32_UP);
_iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32_UP + 1);
_iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32_UP + 0x10);
_iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32_UP + 0x11);
break;
case 2:
_iocs_bgtextst (0, x, y, BGPAL_BUTTON32_UP);
_iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32_UP + 1);
_iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32_UP + 0x10);
_iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32_UP + 0x11);
break;
}
}
/* トラックアクティブ状態を表示 */
void DispTrackActive (int track)
{
if (track_active[track])
_iocs_bgtextst (0, ACTIVE_BGX, SC_BGY + track, BGPAL_TRACK_ACTIVE);
else
_iocs_bgtextst (0, ACTIVE_BGX, SC_BGY + track, BGPAL_TRACK_INACTIVE);
}
/* ランプ付き16x16ドットのボタンを表示 */
void DispButtonLamp (int x, int y, int s)
{
if (s)
_iocs_bgtextst (0, x, y, BGPAL_LAMP_ACTIVE);
else
_iocs_bgtextst (0, x, y, BGPAL_LAMP_INACTIVE);
}
/* 1小節表示 */
/* 小節を英語で言うと "bar" たそうで */
void DispScore (int bar_disp)
{
int i, j;
for (j = 0; j < TRACK_MAX; j++) {
if (track_active[j]) {
for (i = 0; i < NOTE_DISP; i++)
_iocs_bgtextst (0, SC_BGX + i, SC_BGY + j,
PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + i] << 8) + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + i]);
} else {
for (i = 0; i < NOTE_DISP; i++)
_iocs_bgtextst (0, SC_BGX + i, SC_BGY + j, PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + i] << 8) + BG_NOTE);
}
}
}
/* .PCM ファイル名を表示&マウスカーソルの色を設定 */
void DispFname (void)
{
int i;
int color_mouse[TYPE_MAX] =
{RGB (31, 0, 0), RGB (0, 31, 0), RGB (0, 0, 31), RGB (31, 31, 0)};
#define FNAME_X 2 /* ファイル名表示座標 */
#define FNAME_Y SC_BGY
/* マウスカーソルの色を設定 */
_iocs_tpalet (8, color_mouse[type_current]);
for (i = 0; i < TRACK_MAX; i++) {
_dos_c_locate (FNAME_X, FNAME_Y + i);
puts (" ");
_dos_c_locate (FNAME_X, FNAME_Y + i);
puts (pcm_fname[type_current][i]);
}
}
/* 左クリックで音符(?)を置く */
void PutNote (int track, int note, int volume, int type)
{
if (track_active[track]) {
note_volume[track][bar_disp * NOTE_DISP + note] = volume;
note_type[track][bar_disp * NOTE_DISP + note] = type;
_iocs_bgtextst (0, SC_BGX + note, SC_BGY + track,
PAL_TYPE0 + (type << 8) + BG_NOTE + volume);
}
}
/* 指定した音符上にマウスカーソルを移動する・KEYDOWN イベント用 */
/* dx,dy は note,track の移動量 */
void SetMousePos (EVENTREC * eventrec, int dx, int dy)
{
int mouse_x = eventrec->mouse_x;
int mouse_y = eventrec->mouse_y;
int track, note;
if (mouse_x >= SC_BGX * 16) {
if (mouse_x < (SC_BGX + NOTE_DISP) * 16) {
/* X座標が楽譜内の場合 */
note = (mouse_x - SC_BGX * 16) / 16;
note += dx;
if (note < 0) {
note = NOTE_DISP - 1;
if (--bar_disp < 0) /* 1小節戻る */
bar_disp = bar_max_table[bar_max] - 1;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
}
if (note >= NOTE_DISP) {
note = 0;
if (++bar_disp >= bar_max_table[bar_max]) /* 1小節先へ */
bar_disp = 0;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
}
} else {
note = NOTE_DISP - 1;
}
} else {
note = 0;
}
if (mouse_y >= SC_BGY * 16) {
if (mouse_y < (SC_BGY + TRACK_MAX) * 16) {
/* Y座標が楽譜内の場合 */
track = (mouse_y - SC_BGY * 16) / 16;
track += dy;
if (track < 0)
track = TRACK_MAX - 1;
else if (track >= TRACK_MAX)
track = 0;
} else {
track = TRACK_MAX - 1;
}
} else {
track = 0;
}
#define MOUSE_OFFSET_X 12
#define MOUSE_OFFSET_Y 12
_iocs_ms_curst (SC_BGX * 16 + note * 16 + MOUSE_OFFSET_X, SC_BGY * 16 + track * 16 + MOUSE_OFFSET_Y);
}
/* マウスカーソル上の音符をの音量を変更する・KEYDOWN イベント用 */
/* dv = 増減する値 0なら音符を消す */
void SetVolume (EVENTREC * eventrec, int dv)
{
if ((eventrec->mouse_x >= SC_BGX * 16) && (eventrec->mouse_x < (SC_BGX + NOTE_DISP) * 16)
&& (eventrec->mouse_y >= SC_BGY * 16) && (eventrec->mouse_y < (SC_BGY + TRACK_MAX) * 16)) {
int note, track;
int type, volume;
note = (eventrec->mouse_x - SC_BGX * 16) / 16;
track = (eventrec->mouse_y - SC_BGY * 16) / 16;
type = note_type[track][bar_disp * NOTE_DISP + note];
volume = note_volume[track][bar_disp * NOTE_DISP + note];
if (volume == 0) {
PutNote (track, note, 8, type_current);
} else {
if (dv)
volume += dv;
else
volume = 0;
if (volume <= 0)
volume = 0;
else if (volume > 15)
volume = 15;
PutNote (track, note, volume, type);
}
}
}
/* [Z][X][C][V] で直接音符を置く・KEYDOWN イベント用 */
void SetAbsNote (EVENTREC * eventrec, int type)
{
if ((eventrec->mouse_x >= SC_BGX * 16) && (eventrec->mouse_x < (SC_BGX + NOTE_DISP) * 16)
&& (eventrec->mouse_y >= SC_BGY * 16) && (eventrec->mouse_y < (SC_BGY + TRACK_MAX) * 16)) {
int note, track;
int volume;
note = (eventrec->mouse_x - SC_BGX * 16) / 16;
track = (eventrec->mouse_y - SC_BGY * 16) / 16;
volume = note_volume[track][bar_disp * NOTE_DISP + note];
if (volume == 0){
volume = 8;
}else{
type_current = type;
DispFname();
}
PutNote (track, note, volume, type);
}
}
void WaitClick (void)
{
while (_iocs_ms_getdt () & 0xff00); /* 左ボタンが離されるのを待つ */
while (!(_iocs_ms_getdt () & 0xff00)); /* 左ボタンが押されるのを待つ */
while (_iocs_ms_getdt () & 0xff00); /* 左ボタンが離されるのを待つ */
}
/* 演奏データをセーブする */
void SaveScore (char *fname)
{
#define MES_X 0
#define MES_Y 28
_dos_c_locate (MES_X, MES_Y);
if (SoundSaveZms (fname) < 0) {
printf ("%s を書き込めません\n", fname);
} else {
if (fname == NULL)
printf ("TEMP.ZMS を書き込みました\n");
else
printf ("%s を書き込みました\n", fname);
}
printf ("マウスをクリックして下さい\n");
WaitClick ();
_dos_c_locate (MES_X, MES_Y);
puts (" \n"
" \n");
}
void WaitVdisp (void)
{
int sp;
volatile unsigned char *GPIP_DATA = (volatile unsigned char *) 0xe88001;
sp = _iocs_b_super (0);
while (!((*GPIP_DATA) & 0x10));
while ((*GPIP_DATA) & 0x10);
_iocs_b_super (sp);
}
void PcmOut (int note)
{
int track;
for (track = 0; track < TRACK_MAX; track++) {
int volume = note_volume[track][bar_play * NOTE_DISP + note];
int type = note_type[track][bar_play * NOTE_DISP + note];
if ((volume) && (track_active[track]))
SoundPcm8Out (track, type, volume);
}
}
/* どの場所でマウスの左/右ボタンが押されたか */
/* 返り値: BPOS_???, eventrec->work1,work2 = その詳細(ボタンによって違う) */
enum {
BPOS_NON = 0, BPOS_SCORE, BPOS_FNAME, BPOS_ACTIVE, BPOS_TEMPO, BPOS_CURRENT, BPOS_MAX,
BPOS_COPY, BPOS_PASTE, BPOS_SAVE, BPOS_CHASE, BPOS_LOOP,
};
int SearchButton (EVENTREC * eventrec)
{
int ret = 1;
struct {
int x0, y0, x1, y1;
} rect[] = {
{ /* なし */
0, 0, 0, 0
},
{ /* 楽譜上 */
SC_BGX *16, SC_BGY * 16, SC_BGX * 16 + NOTE_DISP * 16, SC_BGY * 16 + TRACK_MAX * 16
},
{ /* debug ファイル名上 */
0, 0, 0, 0
},
{ /* アクティブボタン上 */
ACTIVE_BGX *16, SC_BGY * 16, ACTIVE_BGX * 16 + 16, SC_BGY * 16 + TRACK_MAX * 16
},
{ /* TEMPO アップダウンボタン */
(TEMPO_BGX + 3) * 16, TEMPO_BGY * 16, (TEMPO_BGX + 3) * 16 + 32, TEMPO_BGY * 16 + 32
},
{ /* CURRENT アップダウンボタン */
(BARNO_BGX + 2) * 16, BARNO_BGY * 16, (BARNO_BGX + 2) * 16 + 32, BARNO_BGY * 16 + 32
},
{ /* MAX アップダウンボタン */
(MAXBARNO_BGX + 2) * 16, MAXBARNO_BGY * 16, (MAXBARNO_BGX + 2) * 16 + 32, MAXBARNO_BGY * 16 + 32
},
{
COPY_BGX *16, COPY_BGY * 16, COPY_BGX * 16 + 32, COPY_BGY * 16 + 32
},
{
PASTE_BGX *16, PASTE_BGY * 16, PASTE_BGX * 16 + 32, PASTE_BGY * 16 + 32
},
{
SAVE_BGX *16, SAVE_BGY * 16, SAVE_BGX * 16 + 32, SAVE_BGY * 16 + 32
},
{
CHASE_BGX *16, CHASE_BGY * 16, CHASE_BGX * 16 + 16, CHASE_BGY * 16 + 16
},
{
LOOP_BGX *16, LOOP_BGY * 16, LOOP_BGX * 16 + 16, LOOP_BGY * 16 + 16
},
{ /* エンドコード */
-1, -1, -1, -1
},
};
for (;;) {
if (rect[ret].x0 < 0) {
ret = 0;
break;
}
if ((eventrec->mouse_x >= rect[ret].x0) && (eventrec->mouse_x < rect[ret].x1)
&& (eventrec->mouse_y >= rect[ret].y0) && (eventrec->mouse_y < rect[ret].y1)) {
switch (ret) {
case BPOS_NON:
default:
break;
case BPOS_SCORE:
eventrec->work1 = (eventrec->mouse_x - SC_BGX * 16) / 16; /* note_no */
eventrec->work2 = (eventrec->mouse_y - SC_BGY * 16) / 16; /* track_no */
break;
case BPOS_FNAME:
break;
case BPOS_ACTIVE:
/* どのトラックのボタンが押されたかを work1 に返す */
eventrec->work1 = (eventrec->mouse_y - SC_BGY * 16) / 16; /* track_no */
break;
case BPOS_TEMPO:
case BPOS_CURRENT:
case BPOS_MAX:
/* アップボタンかダウンボタンかを work1 に返す */
eventrec->work1 = (eventrec->mouse_x < rect[ret].x0 + 16);
break;
}
break;
}
ret++;
}
return (ret);
}
/* キー入力をチェック */
void CheckKey (EVENTREC * eventrec)
{
int k;
eventrec->keycode = KEYDOWN_NON;
#define KEY_ESC 2
if (_iocs_bitsns (0) & KEY_ESC)
eventrec->keycode = KEYDOWN_ESC;
#define KEY_Z 0x04
#define KEY_X 0x08
#define KEY_C 0x10
#define KEY_V 0x20
k = _iocs_bitsns (0x05);
if (k & KEY_Z)
eventrec->keycode = KEYDOWN_Z;
if (k & KEY_X)
eventrec->keycode = KEYDOWN_X;
if (k & KEY_C)
eventrec->keycode = KEYDOWN_C;
if (k & KEY_V)
eventrec->keycode = KEYDOWN_V;
#define KEY_DEL 0x80
#define KEY_SPACE 0x20
k = _iocs_bitsns (0x06);
if (k & KEY_DEL)
eventrec->keycode = KEYDOWN_DEL;
if (k & KEY_SPACE)
eventrec->keycode = KEYDOWN_SPACE;
#define KEY_ROLLUP 0x01
#define KEY_ROLLDOWN 0x02
#define KEY_UNDO 0x04
#define KEY_LEFT 0x08
#define KEY_UP 0x10
#define KEY_RIGHT 0x20
#define KEY_DOWN 0x40
k = _iocs_bitsns (0x07);
if (k & KEY_LEFT)
eventrec->keycode = KEYDOWN_LEFT;
if (k & KEY_RIGHT)
eventrec->keycode = KEYDOWN_RIGHT;
if (k & KEY_UP)
eventrec->keycode = KEYDOWN_UP;
if (k & KEY_DOWN)
eventrec->keycode = KEYDOWN_DOWN;
if (k & KEY_ROLLUP)
eventrec->keycode = KEYDOWN_ROLLUP;
if (k & KEY_ROLLDOWN)
eventrec->keycode = KEYDOWN_ROLLDOWN;
if (k & KEY_UNDO)
eventrec->keycode = KEYDOWN_UNDO;
#define KEY_XF1 0x20
#define KEY_XF2 0x40
k = _iocs_bitsns (0x0a);
if (k & KEY_XF1)
eventrec->keycode = KEYDOWN_XF1;
if (k & KEY_XF2)
eventrec->keycode = KEYDOWN_XF2;
#define KEY_BREAK 2
if (_iocs_bitsns (0x0c) & KEY_BREAK)
eventrec->keycode = KEYDOWN_BREAK;
if (eventrec->keycode != KEYDOWN_NON)
eventrec->type = EVENT_KEYDOWN;
}
/* イベントを取得する */
void GetEvent (EVENTREC * eventrec)
{
unsigned int ms_pos, ms_getdt;
#define MS_BUTTON_LEFT 0xff00
#define MS_BUTTON_RIGHT 0x00ff
ms_pos = _iocs_ms_curgt ();
ms_getdt = _iocs_ms_getdt ();
eventrec->old_type = eventrec->type;
eventrec->old_mouse_x = eventrec->mouse_x;
eventrec->old_mouse_y = eventrec->mouse_y;
eventrec->old_mouse_pat = eventrec->mouse_pat;
eventrec->mouse_x = (ms_pos >> 16);
eventrec->mouse_y = (ms_pos & 0xffff);
if (ms_getdt & MS_BUTTON_LEFT) {
if (ms_getdt & MS_BUTTON_RIGHT)
eventrec->type = EVENT_MSLRDOWN;
else
eventrec->type = EVENT_MSLDOWN;
} else {
if (ms_getdt & MS_BUTTON_RIGHT) {
eventrec->type = EVENT_MSRDOWN;
} else {
eventrec->type = EVENT_MSLRUP;
/* マウスのボタンが押されていない時だけキー入力をチェック */
CheckKey (eventrec);
}
}
/* [SHIFT] キーはキーダウンイベントを発生させないのに注意 */
#define KEY_SHIFT 1
eventrec->shift_key = (_iocs_bitsns (0x0e) & KEY_SHIFT);
return;
}
void EventLoop (char *fname)
{
int i, j;
int note_counter = 0;
EVENTREC _eventrec, *eventrec = &_eventrec;
int exit_flag = 0;
int repeat_time = 0;
int bar_note = 0; /* 現在演奏中の音符 */
/* bar_play*NOTE_DISP + note_no が現在演奏中の音符になる */
int button32_up = BPOS_NON;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispUpdown (BARNO_BGX + 2, BARNO_BGY);
DispTwoNumber (MAXBARNO_BGX, MAXBARNO_BGY, bar_max_table[bar_max]);
DispUpdown (MAXBARNO_BGX + 2, MAXBARNO_BGY);
tempo = VDISP60SEC / 4 / note_tempo;
DispThreeNumber (TEMPO_BGX, TEMPO_BGY, tempo);
DispUpdown (TEMPO_BGX + 3, TEMPO_BGY);
DispButton32 (COPY_BGX, COPY_BGY, 0);
DispButton32 (PASTE_BGX, PASTE_BGY, 0);
DispButton32 (SAVE_BGX, SAVE_BGY, 0);
DispButtonLamp (CHASE_BGX, CHASE_BGY, 0);
DispButtonLamp (LOOP_BGX, LOOP_BGY, 0);
/* 垂直同期ごとにループ */
do {
WaitVdisp ();
/* note_counter が note_tempo を越えるごとに発音 */
if ((!pause) && (++note_counter >= note_tempo)) {
note_counter = 0;
PcmOut (bar_note); /* 発音 */
if (++bar_note >= NOTE_DISP) {
bar_note = 0;
if (!loop) {
if (++bar_play >= bar_max_table[bar_max])
bar_play = 0;
if (chase) { /* 演奏する小節を追いかけて表示 */
bar_disp = bar_play;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
}
}
}
FlashNote (bar_note); /* 音符を光らせる */
continue; /* 発音した時はイベントを取得しない(モタり防止) */
}
GetEvent (eventrec); /* イベントを取得 */
switch (eventrec->type) {
case EVENT_MSLRUP:
/* 押した32x32ボタンを戻す処理 */
switch (button32_up) {
case BPOS_COPY:
DispButton32 (COPY_BGX, COPY_BGY, 0);
button32_up = BPOS_NON;
break;
case BPOS_PASTE:
DispButton32 (PASTE_BGX, PASTE_BGY, 0);
button32_up = BPOS_NON;
break;
case BPOS_SAVE:
DispButton32 (SAVE_BGX, SAVE_BGY, 0);
button32_up = BPOS_NON;
break;
default:
break;
}
break;
case EVENT_MSLDOWN:
/* 押しっぱなし? */
if (eventrec->type == eventrec->old_type)
break;
switch (SearchButton (eventrec)) {
case BPOS_NON:
default:
break;
case BPOS_SCORE: /* 楽譜上でクリックされた */
{
int note_no, track_no, volume, type;
note_no = eventrec->work1;
track_no = eventrec->work2;
/* 音符を取得する */
volume = note_volume[track_no][bar_disp * NOTE_DISP + note_no];
if (volume == 0) {
/* まだ音符が置かれていない時 */
volume = 8;
type = type_current;
} else {
/* 既に音符が置かれている時 */
if (!eventrec->shift_key) {
if (volume < 15)
volume++;
} else {
/* [SHIFT] 併用の場合は音量を1つ減らす */
if (volume > 0)
volume--;
}
type = note_type[track_no][bar_disp * NOTE_DISP + note_no];
}
PutNote (track_no, note_no, volume, type);
}
break;
case BPOS_FNAME:
break;
case BPOS_ACTIVE: /* アクティブボタン */
track_active[eventrec->work1] = !track_active[eventrec->work1];
DispTrackActive (eventrec->work1);
DispScore (bar_disp);
break;
case BPOS_TEMPO:
if (eventrec->work1) { /* テンポダウン */
note_tempo++;
if (note_tempo > 22)
note_tempo = 22;
} else { /* テンポアップ */
note_tempo--;
if (note_tempo < 2)
note_tempo = 2;
}
tempo = VDISP60SEC / 4 / note_tempo;
DispThreeNumber (TEMPO_BGX, TEMPO_BGY, tempo);
break;
case BPOS_CURRENT:
if (eventrec->work1) { /* 表示小節ダウン */
if (--bar_disp < 0)
bar_disp = bar_max_table[bar_max] - 1;
} else { /* 表示小節アップ */
if (++bar_disp >= bar_max_table[bar_max])
bar_disp = 0;
}
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
break;
case BPOS_MAX:
if (eventrec->work1) { /* 最大小節ダウン */
if (--bar_max < 0)
bar_max = 4;
if (bar_disp >= bar_max_table[bar_max]) {
bar_disp = bar_max_table[bar_max] - 1;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
}
} else { /* 最大小節アップ */
if (++bar_max > 4)
bar_max = 0;
}
DispTwoNumber (MAXBARNO_BGX, MAXBARNO_BGY, bar_max_table[bar_max]);
break;
case BPOS_COPY:
for (j = 0; j < TRACK_MAX; j++) {
for (i = 0; i < NOTE_DISP; i++) {
copy_type[j][i] = note_type[j][bar_disp * NOTE_DISP + i];
copy_volume[j][i] = note_volume[j][bar_disp * NOTE_DISP + i];
}
}
button32_up = BPOS_COPY;
DispButton32 (COPY_BGX, COPY_BGY, 1);
break;
case BPOS_PASTE:
for (j = 0; j < TRACK_MAX; j++) {
for (i = 0; i < NOTE_DISP; i++) {
if (track_active[j]) {
note_type[j][bar_disp * NOTE_DISP + i] = copy_type[j][i];
note_volume[j][bar_disp * NOTE_DISP + i] = copy_volume[j][i];
}
}
}
button32_up = BPOS_PASTE;
DispScore (bar_disp);
DispButton32 (PASTE_BGX, PASTE_BGY, 1);
break;
case BPOS_SAVE:
button32_up = BPOS_SAVE;
DispButton32 (SAVE_BGX, SAVE_BGY, 1);
SaveScore (fname);
break;
case BPOS_CHASE:
chase = !chase;
DispButtonLamp (CHASE_BGX, CHASE_BGY, chase);
bar_disp = bar_play;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
break;
case BPOS_LOOP:
loop = !loop;
DispButtonLamp (LOOP_BGX, LOOP_BGY, loop);
bar_disp = bar_play;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
break;
}
break;
case EVENT_MSRDOWN:
/* 押しっぱなし? */
if (eventrec->type == eventrec->old_type)
break;
switch (SearchButton (eventrec)) {
default:
break;
case BPOS_SCORE: /* 楽譜上でクリックされた */
{
int note_no, track_no, volume;
note_no = eventrec->work1;
track_no = eventrec->work2;
/* 音符を置く */
volume = note_volume[track_no][bar_disp * NOTE_DISP + note_no];
if (volume == 0) {
/* 右クリックで色を変える */
if (!eventrec->shift_key) {
if (++type_current >= TYPE_MAX)
type_current = 0;
} else {
/* [SHIFT] 併用の場合は色を逆順に */
if (--type_current < 0)
type_current = TYPE_MAX - 1;
}
DispFname ();
} else {
/* 既に音符が置かれている時 */
PutNote (track_no, note_no, 0, 0); /* 音符を消す */
}
}
}
break;
case EVENT_MSLRDOWN:
break;
case EVENT_KEYDOWN:
/* 押しっぱなし? */
if (eventrec->type == eventrec->old_type) {
if (--repeat_time <= 0)
repeat_time = REPEAT_2ND;
else
break;
} else {
repeat_time = REPEAT_1ST;
}
switch (eventrec->keycode) {
case KEYDOWN_LEFT:
SetMousePos (eventrec, -1, 0);
break;
case KEYDOWN_RIGHT:
SetMousePos (eventrec, 1, 0);
break;
case KEYDOWN_UP:
SetMousePos (eventrec, 0, -1);
break;
case KEYDOWN_DOWN:
SetMousePos (eventrec, 0, 1);
break;
case KEYDOWN_ROLLUP:
SetVolume (eventrec, 1);
break;
case KEYDOWN_ROLLDOWN:
SetVolume (eventrec, -1);
break;
case KEYDOWN_Z:
SetAbsNote (eventrec, 0);
break;
case KEYDOWN_X:
SetAbsNote (eventrec, 1);
break;
case KEYDOWN_C:
SetAbsNote (eventrec, 2);
break;
case KEYDOWN_V:
SetAbsNote (eventrec, 3);
break;
case KEYDOWN_UNDO:
if (!eventrec->shift_key) {
if (++type_current >= TYPE_MAX)
type_current = 0;
} else {
/* [SHIFT] 併用の場合は色を逆順に */
if (--type_current < 0)
type_current = TYPE_MAX - 1;
}
DispFname ();
break;
case KEYDOWN_DEL:
case KEYDOWN_SPACE:
SetVolume (eventrec, 0);
break;
case KEYDOWN_XF1: /* 表示小節ダウン */
if (--bar_disp < 0)
bar_disp = bar_max_table[bar_max] - 1;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
break;
case KEYDOWN_XF2: /* 表示小節アップ */
if (++bar_disp >= bar_max_table[bar_max])
bar_disp = 0;
DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
DispScore (bar_disp);
break;
case KEYDOWN_ESC:
while (_iocs_bitsns (0) & KEY_ESC); /* [ESC] が離されるのを待つ */
pause = !pause;
break;
case KEYDOWN_BREAK:
exit_flag = !0;
break;
default:
break;
}
break;
default:
break;
}
} while (!exit_flag);
}
/* ファイルを読み込んでポインタを返す */
char *LoadFile (char *fname)
{
FILE *fp;
char *content;
int filesize;
fp = fopen (fname, "rb");
if (fp == NULL) {
/* 実行ファイルと同じパスにしてもう1回オープン */
char temp_fname[92];
strcpy (temp_fname, mypsp->exe_path);
_addlastsep (temp_fname);
strcat (temp_fname, fname);
fp = fopen (temp_fname, "rb");
if (fp == NULL) {
printf ("%s を読み込めません\n", fname);
return (NULL);
}
}
fseek (fp, 0, SEEK_END);
filesize = ftell (fp);
fseek (fp, 0, SEEK_SET);
content = malloc (filesize);
if (content == NULL) {
printf ("メモリが足りません\n");
fclose (fp);
return (NULL);
}
fread (content, sizeof (char), filesize, fp);
fclose (fp);
return (content);
}
void Tini (void)
{
SoundTini0 ();
_iocs_ms_init ();
_iocs_ms_curof ();
if (screen_init)
_iocs_crtmod (16);
_dos_kflushio (0xff); /* キーバッファをクリア */
_dos_c_curon ();
_iocs_skey_mod (-1, 0, 0);
}
int Init (char *fname)
{
int i, j;
int sp;
int track, note_abs;
bar_max = 0; /* 最大の小節数 */
note_tempo = 6; /* この回数垂直同期を待つごとに発音(16分音符) */
{
int table[BAR_MAX_TABLE] =
{1, 2, 4, 8, BAR_MAX};
for (i = 0; i < BAR_MAX_TABLE; i++)
bar_max_table[i] = table[i];
}
if (Pcm8KeepCheck ()) {
printf ("PCM8 が常駐していません\n");
return (-1);
}
/* 演奏データを初期化 */
for (track = 0; track < TRACK_MAX; track++) {
for (note_abs = 0; note_abs < BAR_MAX * NOTE_DISP; note_abs++) {
note_volume[track][note_abs] = 0;
note_type[track][note_abs] = 0;
}
}
if (SoundInit0 (fname))
return (-1);
/* .ZMS 読み込み */
if (fname == NULL) {
/* TR68K.ZMS 読み込み */
if (SoundLoadZms ("TR68K.ZMS") < 0) {
char temp_fname[92];
/* 実行ファイルと同じパスにしてもう1回オープン */
strcpy (temp_fname, mypsp->exe_path);
_addlastsep (temp_fname);
strcat (temp_fname, "TR68K.ZMS");
if (SoundLoadZms (temp_fname) < 0) {
printf ("TR68K.ZMS を読み込めません\n");
return (-1);
}
}
} else {
if (SoundLoadZms (fname) < 0) {
printf ("%s を読み込めません\n", fname);
return (-1);
}
}
sp_data = LoadFile ("TR68K.SP");
if (sp_data == NULL)
return (-1);
pal_data = LoadFile ("TR68K.PAL");
if (pal_data == NULL)
return (-1);
_iocs_crtmod (12);
_iocs_g_clr_on ();
_iocs_sp_init ();
if (apic_load ("TR68K.PIC", 0, 0)) {
char temp_fname[92];
strcpy (temp_fname, mypsp->exe_path);
_addlastsep (temp_fname);
strcat (temp_fname, "TR68K.PIC");
if (apic_load (temp_fname, 0, 0)) {
printf ("TR68K.PIC を読み込めません\n");
return (-1);
}
}
screen_init = !0;
_dos_c_curoff ();
_iocs_ms_init ();
_iocs_skey_mod (0, 0, 0);
_iocs_ms_curon ();
/* スプライトパターンの設定 */
{
char *sp_ptr = sp_data;
for (i = 0; i < 0x60; i++) {
_iocs_sp_defcg (i, 1, sp_ptr);
sp_ptr += 128;
}
}
/* パレットデータの設定 */
{
unsigned short *pal_ptr = (unsigned short *) pal_data;
for (i = 1; i < 7; i++)
for (j = 0; j < 16; j++)
_iocs_spalet (0x80000000 + j, i, *pal_ptr++); /* 垂直同期検出なし */
/* _iocs_spalet (0x80 + j, i, *pal_ptr++); LIBC のマニュアルは間違い */
}
_iocs_sp_on ();
_iocs_bgctrlst (0, 0, 1);
sp = _iocs_b_super (0);
*(unsigned short *) 0xe82500 = 0b01001011100100; /* 優先順位 TX>SP>GR */
_iocs_b_super (sp);
/* トラックアクティブ状態を初期化(全部アクティブに) */
for (i = 0; i < TRACK_MAX; i++) {
track_active[i] = !0;
DispTrackActive (i);
}
/* コピーバッファを初期化 */
for (track = 0; track < TRACK_MAX; track++) {
for (i = 0; i < NOTE_DISP; i++) {
copy_type[track][i] = 0;
copy_volume[track][i] = 0;
}
}
DispScore (0);
DispFname ();
return (0);
}
int main (int argc, char *argv[])
{
int i;
int slash_flag = 0;
char *fname = NULL; /* .ZMS ファイル名 */
mypsp = _dos_getpdb ();
{
char *temp;
temp = getenv ("SLASH");
if ((temp != NULL) && (*temp == '/'))
slash_flag = !0;
}
for (i = 1; i < argc; i++) {
if (('-' == *argv[i]) || ((!slash_flag) && ('/' == *argv[i]))) {
switch (*(argv[i] + 1)) {
default:
usage ();
return (-1);
}
} else {
fname = argv[i];
}
}
if (!Init (fname))
EventLoop (fname);
Tini ();
return (0);
}